/*
Copyright [2020] [https://www.xiaonuo.vip]

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Snowy采用APACHE LICENSE 2.0开源协议，您在使用过程中，需要注意以下几点：

1.请不要删除和修改根目录下的LICENSE文件。
2.请不要删除和修改Snowy源码头部的版权声明。
3.请保留源码和相关描述文件的项目出处，作者声明等。
4.分发源码时候，请注明软件出处 https://gitee.com/xiaonuobase/snowy
5.在修改包名，模块名称，项目代码等时，请注明软件出处 https://gitee.com/xiaonuobase/snowy
6.若您的项目无法满足以上几点，可申请商业授权，获取Snowy商业授权许可，请在官网购买授权，地址为 https://www.xiaonuo.vip
 */
package vip.xiaonuo.facedoor.modular.memberuser.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.ListUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.http.client.utils.DateUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import reactor.core.Reactor;
import reactor.event.Event;
import vip.xiaonuo.core.consts.CommonConstant;
import vip.xiaonuo.core.context.constant.ConstantContextHolder;
import vip.xiaonuo.core.exception.ServiceException;
import vip.xiaonuo.core.factory.PageFactory;
import vip.xiaonuo.core.pojo.page.PageResult;
import vip.xiaonuo.core.util.IpAddressUtil;
import vip.xiaonuo.core.util.PoiUtil;
import vip.xiaonuo.facedoor.modular.device.entity.DeviceCategory;
import vip.xiaonuo.facedoor.modular.devicebase.entity.DeviceBase;
import vip.xiaonuo.facedoor.modular.devicebase.service.DeviceBaseService;
import vip.xiaonuo.facedoor.modular.memberdevice.constant.MemberDeviceConstant;
import vip.xiaonuo.facedoor.modular.memberdevice.entity.MemberDevice;
import vip.xiaonuo.facedoor.modular.memberdevice.mapper.MemberDeviceMapper;
import vip.xiaonuo.facedoor.modular.memberdevice.vo.MemberDeviceVO;
import vip.xiaonuo.facedoor.modular.memberfacestaris.entity.MemberFaceStaris;
import vip.xiaonuo.facedoor.modular.memberfacestaris.service.MemberFaceStarisService;
import vip.xiaonuo.facedoor.modular.memberfeatures.entity.MemberFeatures;
import vip.xiaonuo.facedoor.modular.memberfeatures.enums.MemberFeaturesTypeEnum;
import vip.xiaonuo.facedoor.modular.memberuser.entity.MemberUser;
import vip.xiaonuo.facedoor.modular.memberuser.enums.MemberUserExceptionEnum;
import vip.xiaonuo.facedoor.modular.memberuser.mapper.MemberUserMapper;
import vip.xiaonuo.facedoor.modular.memberuser.param.MemberUserOrgChangeEventBean;
import vip.xiaonuo.facedoor.modular.memberuser.param.MemberUserParam;
import vip.xiaonuo.facedoor.modular.memberuser.service.FacedoorMemberUserService;
import vip.xiaonuo.facedoor.modular.memberuser.service.MemberUserService;
import vip.xiaonuo.facedoor.modular.memberuser.vo.*;
import vip.xiaonuo.facedoor.modular.orgdevice.entity.OrgDevice;
import vip.xiaonuo.facedoor.modular.orgdevice.mapper.OrgDeviceMapper;
import vip.xiaonuo.facedoor.modular.topic.AiBoxEventTopic;
import vip.xiaonuo.facedoor.modular.topic.EventTopic;
import vip.xiaonuo.facedoor.rule.KSRulesEngine;
import vip.xiaonuo.sys.modular.file.enums.FileTypeEnum;
import vip.xiaonuo.sys.modular.file.service.SysFileInfoService;
import vip.xiaonuo.sys.modular.org.entity.SysOrg;
import vip.xiaonuo.sys.modular.org.mapper.SysOrgMapper;
import vip.xiaonuo.sys.modular.pos.entity.SysPos;
import vip.xiaonuo.sys.modular.pos.service.SysPosService;

import javax.annotation.Resource;
import java.io.File;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * 内部人员service接口实现类
 *
 * @author 胡鹏达
 * @date 2022-07-09 15:48:24
 */
@Service
@Slf4j
@Transactional
public class FacedoorMemberUserServiceImpl implements FacedoorMemberUserService {

    @Resource
    private MemberUserService memberUserService;

    @Resource
    private MemberDeviceMapper memberDeviceMapper;

    @Resource
    private OrgDeviceMapper orgDeviceMapper;

    @Resource
    private MemberUserMapper memberUserMapper;

    @Resource
    private SysOrgMapper sysOrgMapper;

    @Resource
    private SysFileInfoService sysFileInfoService;

    @Resource
    private DeviceBaseService deviceBaseService;

    @Resource
    private SysPosService posService;

    @Autowired
    private Reactor reactor;



    @Resource
    private MemberFaceStarisService faceStarisService;



    @Override
    public PageResult<MemberUserPageVO> page(MemberUserParam memberUserParam) {
        return new PageResult<MemberUserPageVO>(memberUserMapper.findPage(PageFactory.defaultPage(), memberUserParam));
    }

    @Override
    public void export(MemberUserParam memberUserParam) {
        List<MemberUserPageVO> memberUserPageVOS = memberUserMapper.findList(memberUserParam);
        memberUserPageVOS.forEach(x -> {
            if (StringUtils.isNotEmpty(x.getPhoto())) {
                x.setPhoto(IpAddressUtil.getImageAddIp(x.getPhoto()));
            }
        });
        PoiUtil.exportExcelWithStream("内部人员.xls", MemberUserPageVO.class, memberUserPageVOS);
    }

    @Override
    public void exportMemberFaceStairs(MemberUserParam memberUserParam) {
        List<MemberFaceStairsExportVO> listMemberFaceStairs = memberUserMapper.findListMemberFaceStairs(memberUserParam.getId());
        PoiUtil.exportExcelWithStream("人员梯控权限.xls", MemberFaceStairsExportVO.class, listMemberFaceStairs);
    }

    @Override
    public List<MemberUser> list(MemberUserParam memberUserParam) {
        return memberUserService.list();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(MemberUserParam memberUserParam) {
        if (!ConstantContextHolder.getRemotePush()) {
            addMemberUserCheck(memberUserParam);
        }
        addMember(memberUserParam);
    }

    public void addMember(MemberUserParam memberUserParam) {
        MemberUser memberUser = new MemberUser();
        if (memberUserParam.getPosId() != null) {
            SysPos pos = posService.getById(memberUserParam.getPosId());
            memberUser.setPosName(pos.getName());
        }
        BeanUtil.copyProperties(memberUserParam, memberUser);
        setMemberReadCardStatus(memberUser);
        memberUserService.save(memberUser);

        // 珊珊来辞定制
        List<MemberFaceStaris> memberFaceStarisParams = memberUserParam.getMemberFaceStarises();
        if (CollectionUtils.isNotEmpty(memberFaceStarisParams)){
            for (MemberFaceStaris memberFaceStarisParam : memberFaceStarisParams) {
                memberFaceStarisParam.setMemberId(memberUser.getId());
            }
            faceStarisService.saveBatch(memberFaceStarisParams);
        }

        List<OrgDevice> orgDevices = orgDeviceMapper.selectList(new LambdaQueryWrapper<OrgDevice>().eq(OrgDevice::getOrgId, memberUserParam.getOrgId()));
        for (OrgDevice orgDevice : orgDevices) {
            MemberDevice memberDevice = new MemberDevice().setStatus(1).setOrgId(memberUser.getOrgId()).setDeviceId(orgDevice.getDeviceId()).setMemberId(memberUser.getId());
            memberDeviceMapper.insert(memberDevice);
        }

        // 判断是否上传了头像
        if (StringUtils.isNotEmpty(memberUser.getPhoto())) {
            // 发布头像上传的事件
            reactor.notify(AiBoxEventTopic.AVATAR_CHANGE, Event.wrap(memberUser));
        }
        memberUserParam.setId(memberUser.getId());
    }

    @Override
    public List<Dict> listAdminUser(Long deviceId) {
        List<MemberDeviceVO> memberUsers = memberDeviceMapper.listDeviceUser(deviceId);
        List<Dict> dictList = CollectionUtil.newArrayList();
        memberUsers.forEach(sysUser -> {
            Dict dict = Dict.create();
            dict.put(CommonConstant.ID, sysUser.getMemberUserId());
            dict.put(CommonConstant.NAME, sysUser.getName());
            dictList.add(dict);
        });
        return dictList;

    }


    public void addMemberUserCheck(MemberUserParam memberUserParam) {
        SysOrg sysOrg = sysOrgMapper.selectById(memberUserParam.getOrgId());
        if (sysOrg == null || !ObjectUtil.equal(sysOrg.getType(), 1)) {
            throw new ServiceException(500, "请选择员工组!");
        }

        // 插入中间表
        List<OrgDevice> orgDevices = orgDeviceMapper.selectList(new LambdaQueryWrapper<OrgDevice>().eq(OrgDevice::getOrgId, memberUserParam.getOrgId()));
        if (CollectionUtils.isNotEmpty(orgDevices)) {
            List<Long> deviceIds = orgDevices.stream().map(OrgDevice::getDeviceId).collect(Collectors.toList());
            List<DeviceBase> list = deviceBaseService.list(new LambdaQueryWrapper<DeviceBase>().eq(DeviceBase::getDeviceSyncStatus, 2).in(DeviceBase::getId, deviceIds));
            if (CollectionUtils.isNotEmpty(list)) {
                throw new ServiceException(500, "设备正在更换用户组！ 请稍后再试！");
            }
        }
        if (StringUtils.isNotBlank(memberUserParam.getIcCard())) {
            long count = memberUserService.count(new LambdaQueryWrapper<MemberUser>().eq(MemberUser::getIcCard, memberUserParam.getIcCard()));
            if (count > 0) {
                throw new ServiceException(500, "卡号重复!");
            }
        }

        if (StringUtils.isNotBlank(memberUserParam.getTel())) {
            long count = memberUserService.count(new LambdaQueryWrapper<MemberUser>().eq(MemberUser::getTel, memberUserParam.getTel()));
            if (count > 0) {
                throw new ServiceException(500, "手机号码重复!");
            }
        }
        if (StringUtils.isNotBlank(memberUserParam.getJobNum())) {
            long count = memberUserService.count(new LambdaQueryWrapper<MemberUser>().eq(MemberUser::getJobNum, memberUserParam.getJobNum()));
            if (count > 0) {
                throw new ServiceException(500, "工号重复!");
            }
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(MemberUserParam memberUserParam) {
        List<MemberDevice> memberDevices = null;
        MemberUser memberUser = this.queryMemberUser(memberUserParam);
        if (!ConstantContextHolder.getRemotePush()) {
            checkCurrentMemberStatus(memberUser);
            checkUserIsChanging(memberUser);
            checkDeviceStatus(memberUser.getOrgId());
            memberDevices = memberDeviceMapper.selectList(new LambdaQueryWrapper<MemberDevice>().eq(MemberDevice::getMemberId, memberUser.getId())
                    .in(MemberDevice::getStatus, MemberDeviceConstant.ADD_FAIL, MemberDeviceConstant.UPDATE_FAIL, MemberDeviceConstant.DELETE_FAIL, MemberDeviceConstant.SYNC_SUCCESS));
        } else {
            memberDevices = memberDeviceMapper.selectList(new LambdaQueryWrapper<MemberDevice>().eq(MemberDevice::getMemberId, memberUser.getId())
                    .in(MemberDevice::getStatus,
                            MemberDeviceConstant.ADD_FAIL,
                            MemberDeviceConstant.UPDATE_FAIL,
                            MemberDeviceConstant.DELETE_FAIL,
                            MemberDeviceConstant.ADD,
                            MemberDeviceConstant.UPDATE,
                            MemberDeviceConstant.SYNC_SUCCESS));
        }
        for (MemberDevice memberDevice : memberDevices) {
            if (ObjectUtil.equal(MemberDeviceConstant.ADD_FAIL, memberDevice.getStatus())) {
                memberDeviceMapper.deleteById(memberDevice.getId());
                faceStarisService.remove(new LambdaQueryWrapper<MemberFaceStaris>().eq(MemberFaceStaris::getMemberId,memberUser.getId()));
            } else {
                memberDeviceMapper.updateById(memberDevice.setStatus(MemberDeviceConstant.DELETE));
            }
        }
        long count = memberDeviceMapper.selectCount(new LambdaQueryWrapper<MemberDevice>().eq(MemberDevice::getMemberId, memberUser.getId()));
        if (count == 0) {
            memberUserService.removeById(memberUserParam.getId());
            faceStarisService.remove(new LambdaQueryWrapper<MemberFaceStaris>().eq(MemberFaceStaris::getMemberId,memberUser.getId()));
        } else {
            memberUser.setDelFlag("1");
            memberUserService.updateById(memberUser);
        }
        // 通知其他设备人员删除处理
        reactor.notify(EventTopic.MEMBER_DELETE, Event.wrap(memberUser));
        // 发送人脸特征值删除事件
        MemberFeatures memberFeatures = new MemberFeatures();
        memberFeatures.setDwMemberUserId(memberUser.getId());
        memberFeatures.setType(MemberFeaturesTypeEnum.MEMBER.getValue());
        memberFeatures.setPlatform(DeviceCategory.SUB_TYPE_FACE);
        reactor.notify(EventTopic.MEMBER_FACE_VALUE_DELETE, Event.wrap(memberFeatures));

        // 发送人员删除事件,待分析盒处理
        reactor.notify(AiBoxEventTopic.USER_DELETE, Event.wrap(memberUser));
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void edit(MemberUserParam memberUserParam) {
        SysOrg sysOrg = sysOrgMapper.selectById(memberUserParam.getOrgId());
        if (sysOrg == null || !ObjectUtil.equal(sysOrg.getType(), 1)) {
            throw new ServiceException(500, "请选择员工组!");
        }
        MemberUser memberUser = this.queryMemberUser(memberUserParam);
        boolean isAvatarChange = !ObjectUtil.equal(memberUserParam.getPhoto(), memberUser.getPhoto());
        Long currentOrgId = memberUserParam.getOrgId();
        Long originalOrgId = memberUser.getOrgId();
        boolean isOrgChange = !ObjectUtil.equal(currentOrgId, originalOrgId);

        if (!ConstantContextHolder.getRemotePush()) {
            checkCurrentMemberStatus(memberUser);
            checkUserIsChanging(memberUser);
            // 插入中间表
            checkDeviceStatus(memberUser.getOrgId());
            checkDeviceStatus(memberUserParam.getOrgId());
            checkCard(memberUserParam, memberUser);
        }


//        // 黑名单 不下发开启
//        try {
//            TransLimitConfig transconfig = integrationService.getConfig("transconfig", TransLimitConfig.class);
//            if (ObjectUtil.equal(memberUser.getPersonType(), 2) && ObjectUtil.equal(transconfig.getIsBlackList(), 1)) {
//                memberUserParam.setMiniAppMemberId(memberUser.getMiniAppMemberId());
//                BeanUtil.copyProperties(memberUserParam, memberUser);
//                setMemberReadCardStatus(memberUser);
//                if (memberUserParam.getPosId() != null) {
//                    SysPos pos = posService.getById(memberUserParam.getPosId());
//                    memberUser.setPosName(pos.getName());
//                }
//                memberUserService.updateById(memberUser);
//                return;
//            }
//        } catch (IOException e) {
//            throw new RuntimeException(e);
//        }

        // 组织变更 新增和删除人员
        if (!ObjectUtil.equal(memberUser.getOrgId(), memberUserParam.getOrgId())) {
            // 删除只删除不是管理员的
            memberDeviceMapper.updateStateForMemberId(memberUserParam.getId(), 3);
            // 新增人员
            List<OrgDevice> orgDevices = orgDeviceMapper.selectList(new LambdaQueryWrapper<OrgDevice>().eq(OrgDevice::getOrgId, memberUserParam.getOrgId()));
            for (OrgDevice orgDevice : orgDevices) {
                MemberDevice memberDevice = new MemberDevice().setStatus(1).setOrgId(memberUserParam.getOrgId()).setDeviceId(orgDevice.getDeviceId()).setMemberId(memberUser.getId());
                memberDeviceMapper.insert(memberDevice);
            }
            // 修改人员
        } else {
            memberDeviceMapper.updateStateForMemberId(memberUserParam.getId(), 2);
        }
        boolean pushCardUpdateEvent = !ObjectUtil.equal(memberUserParam.getIcCard(), memberUser.getIcCard());
        memberUserParam.setMiniAppMemberId(memberUser.getMiniAppMemberId());
        BeanUtil.copyProperties(memberUserParam, memberUser);
        setMemberReadCardStatus(memberUser);
        if (memberUserParam.getPosId() != null) {
            SysPos pos = posService.getById(memberUserParam.getPosId());
            memberUser.setPosName(pos.getName());
        }
        memberUserService.updateById(memberUser);

        // 先删除再增加
        faceStarisService.remove(new LambdaQueryWrapper<MemberFaceStaris>().eq(MemberFaceStaris::getMemberId,memberUser.getId()));
        List<MemberFaceStaris> memberFaceStarisParams = memberUserParam.getMemberFaceStarises();
        if (CollectionUtils.isNotEmpty(memberFaceStarisParams)){
            for (MemberFaceStaris memberFaceStarisParam : memberFaceStarisParams) {
                memberFaceStarisParam.setId(null);
                memberFaceStarisParam.setMemberId(memberUser.getId());
            }
            faceStarisService.saveBatch(memberFaceStarisParams);
        }

        notifyOther(memberUser, isAvatarChange, currentOrgId, originalOrgId, isOrgChange, pushCardUpdateEvent);
    }

    private void notifyOther(MemberUser memberUser, boolean isAvatarChange, Long currentOrgId, Long originalOrgId, boolean isOrgChange, boolean pushCardUpdateEvent) {
        // 发布人员卡号变动事件
        if (pushCardUpdateEvent) {
            // 通知其他设备人员删除处理
            reactor.notify(EventTopic.MEMBER_UPDATE_CARD, Event.wrap(memberUser.getId()));
        }

        // 头像变更
        if (isAvatarChange) {
            reactor.notify(AiBoxEventTopic.AVATAR_CHANGE, Event.wrap(memberUser));
            // 发送人脸特征值删除事件
            MemberFeatures memberFeatures = new MemberFeatures();
            memberFeatures.setDwMemberUserId(memberUser.getId());
            memberFeatures.setType(MemberFeaturesTypeEnum.MEMBER.getValue());
            memberFeatures.setPlatform(DeviceCategory.SUB_TYPE_FACE);
            reactor.notify(EventTopic.MEMBER_FACE_VALUE_DELETE, Event.wrap(memberFeatures));
        }

        // 组织机构变更
        if (isOrgChange) {
            MemberUserOrgChangeEventBean bean = new MemberUserOrgChangeEventBean();
            bean.setUserId(memberUser.getId());
            bean.setCurrentOrgId(currentOrgId);
            bean.setOriginalOrgId(originalOrgId);
            reactor.notify(AiBoxEventTopic.ORG_EDIT, Event.wrap(bean));
        }
        reactor.notify(EventTopic.MEMBER_UPDATE, Event.wrap(memberUser));
    }

    private void checkCard(MemberUserParam memberUserParam, MemberUser memberUser) {
        if (StringUtils.isNotBlank(memberUserParam.getIcCard())) {
            long count = memberUserService.count(new LambdaQueryWrapper<MemberUser>()
                    .eq(MemberUser::getIcCard, memberUserParam.getIcCard()).ne(MemberUser::getId, memberUser.getId()));
            if (count > 0) {
                throw new ServiceException(500, "卡号重复!");
            }
        }
        if (StringUtils.isNotBlank(memberUserParam.getTel())) {
            long count = memberUserService.count(new LambdaQueryWrapper<MemberUser>().eq(MemberUser::getTel, memberUserParam.getTel()).ne(MemberUser::getId, memberUser.getId()));
            if (count > 0) {
                throw new ServiceException(500, "手机号码重复!");
            }
        }
        if (StringUtils.isNotBlank(memberUserParam.getJobNum())) {
            long count = memberUserService.count(new LambdaQueryWrapper<MemberUser>().eq(MemberUser::getJobNum, memberUserParam.getJobNum()).ne(MemberUser::getId, memberUser.getId()));
            if (count > 0) {
                throw new ServiceException(500, "工号重复!");
            }
        }
    }

    private void setMemberReadCardStatus(MemberUser memberUser) {
        if (StringUtils.isNotEmpty(memberUser.getIcCard())) {
            memberUser.setReadCardStatus("1");
        }
    }

    private void checkDeviceStatus(Long orgId) {
        List<OrgDevice> orgDevices = orgDeviceMapper.selectList(new LambdaQueryWrapper<OrgDevice>().eq(OrgDevice::getOrgId, orgId));
        if (CollectionUtils.isNotEmpty(orgDevices)) {
            List<Long> deviceIds = orgDevices.stream().map(OrgDevice::getDeviceId).collect(Collectors.toList());
            List<DeviceBase> list = deviceBaseService.list(new LambdaQueryWrapper<DeviceBase>().eq(DeviceBase::getDeviceSyncStatus, 2).in(DeviceBase::getId, deviceIds));
            if (CollectionUtils.isNotEmpty(list)) {
                throw new ServiceException(500, "设备正在更换用户组！ 请稍后再试！");
            }
        }
    }

    private void checkCurrentMemberStatus(MemberUser memberUser) {
        long count = memberDeviceMapper.selectCount(new LambdaQueryWrapper<MemberDevice>().eq(MemberDevice::getMemberId, memberUser.getId()).in(MemberDevice::getStatus, MemberDeviceConstant.ADD, MemberDeviceConstant.UPDATE, MemberDeviceConstant.DELETE));
        if (count > 0) {
            throw new ServiceException(500, "设备正在忙碌中！请稍后!");
        }
    }

    private void checkUserIsChanging(MemberUser memberUser) {
        if (KSRulesEngine.memberChangeService != null && KSRulesEngine.memberChangeService.isChanging(memberUser)) {
            throw new ServiceException(500, "该员工正在变更分组关联，请稍后再操作!");
        }
    }

    @Override
    public MemberUser detail(MemberUserParam memberUserParam) {
        return this.queryMemberUser(memberUserParam);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public UserImportResultVO importExcel(MultipartFile file) {

        List<DeviceBase> deviceBases = deviceBaseService.list(new LambdaQueryWrapper<DeviceBase>().eq(DeviceBase::getDeviceSyncStatus, 2));
        if (CollectionUtils.isNotEmpty(deviceBases)) {
            throw new ServiceException(500, "设备正在更换用户组！ 请稍后再试！");
        }
        List<MemberImportResultPojoVO> memberImportResultPojoVos = new CopyOnWriteArrayList<>();
        // 保存文件
        sysFileInfoService.uploadFile(file, FileTypeEnum.USER);
        AtomicInteger successNum = new AtomicInteger(0);
        AtomicInteger failureNum = new AtomicInteger(0);
        List<MemberUserImportVO> memberUserImportVOS = PoiUtil.importExcel(file, 0, 1, MemberUserImportVO.class);
        if (CollectionUtils.isEmpty(memberUserImportVOS)) {
            throw new ServiceException(500, "文件中不存在有效数据!");
        }
        long d = System.currentTimeMillis();
        log.info("====导入开始时间==================================================" + DateUtils.formatDate(new Date()));

        if (memberUserImportVOS.size() > 20) {
            log.info("开始多线程导入===");
            List<List<MemberUserImportVO>> splitList = ListUtils.partition(memberUserImportVOS, memberUserImportVOS.size() / 20);
            CountDownLatch countDownLatch = new CountDownLatch(splitList.size());
            ExecutorService executorService = Executors.newFixedThreadPool(splitList.size());
            for (List<MemberUserImportVO> oneList : splitList) {
                executorService.execute(() -> {
                    try {
                        signalThreadImport(memberImportResultPojoVos, successNum, failureNum, oneList);
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        countDownLatch.countDown();
                    }
                });
            }
            try {
                countDownLatch.await();
            } catch (InterruptedException e) {
                log.error("线程被其他线程中断【{}】", ExceptionUtil.getMessage(e));
            }
        } else {
            log.info("开始单线程导入===");
            signalThreadImport(memberImportResultPojoVos, successNum, failureNum, memberUserImportVOS);
        }
        //有效数据
        log.info("====导入结束时间==================================================" + (System.currentTimeMillis() - d));
        UserImportResultVO memberImportResultVo = new UserImportResultVO();
        memberImportResultVo.setSuccessNum(successNum.get());
        memberImportResultVo.setFailNum(failureNum.get());
        memberImportResultVo.setMemberImportResultPojoVos(memberImportResultPojoVos);
        return memberImportResultVo;
    }

    @Override
    public UserImportResultVO importMemberFaceStairsExcel(MultipartFile file) {

        List<DeviceBase> deviceBases = deviceBaseService.list(new LambdaQueryWrapper<DeviceBase>().eq(DeviceBase::getDeviceSyncStatus, 2));
        if (CollectionUtils.isNotEmpty(deviceBases)) {
            throw new ServiceException(500, "设备正在更换用户组！ 请稍后再试！");
        }
        List<MemberImportResultPojoVO> memberImportResultPojoVos = new CopyOnWriteArrayList<>();
        // 保存文件
        sysFileInfoService.uploadFile(file, FileTypeEnum.USER);
        AtomicInteger successNum = new AtomicInteger(0);
        AtomicInteger failureNum = new AtomicInteger(0);


        List<MemberFaceStairsExportVO> faceStairsVOS = PoiUtil.importExcel(file, 0, 1, MemberFaceStairsExportVO.class);
        if (CollectionUtils.isEmpty(faceStairsVOS)) {
            throw new ServiceException(500, "文件中不存在有效数据!");
        }
        long d = System.currentTimeMillis();
        log.info("====导入开始时间==================================================" + DateUtils.formatDate(new Date()));

        if (faceStairsVOS.size() > 20) {
            log.info("开始多线程导入===");
            List<List<MemberFaceStairsExportVO>> splitList = ListUtils.partition(faceStairsVOS, faceStairsVOS.size() / 20);
            CountDownLatch countDownLatch = new CountDownLatch(splitList.size());
            ExecutorService executorService = Executors.newFixedThreadPool(splitList.size());
            for (List<MemberFaceStairsExportVO> oneList : splitList) {
                executorService.execute(() -> {
                    try {
                        this.signalThreadImportFaceStairs(memberImportResultPojoVos, successNum, failureNum, oneList);
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        countDownLatch.countDown();
                    }
                });
            }
            try {
                countDownLatch.await();
            } catch (InterruptedException e) {
                log.error("线程被其他线程中断【{}】", ExceptionUtil.getMessage(e));
            }
        } else {
            log.info("开始单线程导入===");
            this.signalThreadImportFaceStairs(memberImportResultPojoVos, successNum, failureNum, faceStairsVOS);
        }
        //有效数据
        log.info("====导入结束时间==================================================" + (System.currentTimeMillis() - d));
        UserImportResultVO memberImportResultVo = new UserImportResultVO();
        memberImportResultVo.setSuccessNum(successNum.get());
        memberImportResultVo.setFailNum(failureNum.get());
        memberImportResultVo.setMemberImportResultPojoVos(memberImportResultPojoVos);
        return memberImportResultVo;
    }



    private void signalThreadImportFaceStairs(List<MemberImportResultPojoVO> memberImportResultPojoVos, AtomicInteger successNum, AtomicInteger failureNum, List<MemberFaceStairsExportVO> faceStairs) {
        for (MemberFaceStairsExportVO importBean : faceStairs) {
            try {
                if (StringUtils.isBlank(importBean.getJobNum())) {
                    MemberImportResultPojoVO memberImportResultPojoVo = new MemberImportResultPojoVO();
                    memberImportResultPojoVo.setName(importBean.getMemberName()).setFailMessage("工号为空");
                    memberImportResultPojoVos.add(memberImportResultPojoVo);
                    failureNum.incrementAndGet();
                    continue;
                }
                if (StringUtils.isBlank(importBean.getDeviceCode())) {
                    MemberImportResultPojoVO memberImportResultPojoVo = new MemberImportResultPojoVO();
                    memberImportResultPojoVo.setName(importBean.getMemberName()).setFailMessage("设备编码为空");
                    memberImportResultPojoVos.add(memberImportResultPojoVo);
                    failureNum.incrementAndGet();
                    continue;
                }
                if (StringUtils.isBlank(importBean.getFloors())) {
                    MemberImportResultPojoVO memberImportResultPojoVo = new MemberImportResultPojoVO();
                    memberImportResultPojoVo.setName(importBean.getMemberName()).setFailMessage("楼层为空");
                    memberImportResultPojoVos.add(memberImportResultPojoVo);
                    failureNum.incrementAndGet();
                    continue;
                }

                MemberUser memberUser = memberUserMapper.selectOne(new LambdaQueryWrapper<MemberUser>().eq(MemberUser::getJobNum, importBean.getJobNum()));
                if (memberUser == null) {
                    MemberImportResultPojoVO memberImportResultPojoVo = new MemberImportResultPojoVO();
                    memberImportResultPojoVo.setName(importBean.getMemberName()).setFailMessage("工号错误");
                    memberImportResultPojoVos.add(memberImportResultPojoVo);
                    failureNum.incrementAndGet();
                    continue;
                }

                DeviceBase deviceBase = deviceBaseService.getOne(new LambdaQueryWrapper<DeviceBase>().eq(DeviceBase::getRegistrationCode, importBean.getDeviceCode()));
                if (deviceBase == null) {
                    MemberImportResultPojoVO memberImportResultPojoVo = new MemberImportResultPojoVO();
                    memberImportResultPojoVo.setName(importBean.getDeviceName()).setFailMessage("设备编码错误");
                    memberImportResultPojoVos.add(memberImportResultPojoVo);
                    failureNum.incrementAndGet();
                    continue;
                }

                MemberDevice memberDevice = memberDeviceMapper.selectOne(new LambdaQueryWrapper<MemberDevice>().eq(MemberDevice::getDeviceId, deviceBase.getId()).eq(MemberDevice::getMemberId, memberUser.getId()));
                if (memberDevice==null){
                    MemberImportResultPojoVO memberImportResultPojoVo = new MemberImportResultPojoVO();
                    memberImportResultPojoVo.setName(importBean.getDeviceName()).setFailMessage("设备未对该用户授权");
                    memberImportResultPojoVos.add(memberImportResultPojoVo);
                    failureNum.incrementAndGet();
                    continue;
                }
                faceStarisService.remove(new LambdaQueryWrapper<MemberFaceStaris>().eq(MemberFaceStaris::getMemberId,memberUser.getId()));
                successNum.incrementAndGet();
                memberDevice.setStatus(MemberDeviceConstant.UPDATE);
                memberDeviceMapper.updateById(memberDevice);
                MemberFaceStaris memberFaceStaris = new MemberFaceStaris();
                memberFaceStaris.setMemberId(memberUser.getId());
                memberFaceStaris.setDeviceName(deviceBase.getName());
                memberFaceStaris.setDeviceId(deviceBase.getDeviceId());
                memberFaceStaris.setFloors(importBean.getFloors());
                faceStarisService.save(memberFaceStaris);
            } catch (Exception e) {
                log.error("用户【{}】 发生错误 错误信息【{}】", importBean.getMemberName(), ExceptionUtils.getMessage(e));
                MemberImportResultPojoVO memberImportResultPojoVo = new MemberImportResultPojoVO();
                memberImportResultPojoVo.setName(importBean.getMemberName()).setFailMessage("发生异常错误!"+ ExceptionUtils.getMessage(e));
                memberImportResultPojoVos.add(memberImportResultPojoVo);
                failureNum.incrementAndGet();
            }
        }
    }



    private void signalThreadImport(List<MemberImportResultPojoVO> memberImportResultPojoVos, AtomicInteger successNum, AtomicInteger failureNum, List<MemberUserImportVO> memberUserImportVOS) {
        for (MemberUserImportVO importBean : memberUserImportVOS) {
            try {

                if (StringUtils.isBlank(importBean.getJobNum())) {
                    addFailMessage(memberImportResultPojoVos, importBean, "工号为null", failureNum);
                    continue;
                }

                if (StringUtils.isBlank(importBean.getOrgCode())) {
                    addFailMessage(memberImportResultPojoVos, importBean, "组织为null", failureNum);
                    continue;
                }
                MemberUser memberUser = memberUserMapper.selectOne(new LambdaQueryWrapper<MemberUser>().eq(MemberUser::getJobNum, importBean.getJobNum()));
                if (memberUser != null) {
                    addFailMessage(memberImportResultPojoVos, importBean, "工号重复", failureNum);
                    continue;
                }

                if (StringUtils.isNotBlank(importBean.getIcCard())) {
                    long count = memberUserService.count(new LambdaQueryWrapper<MemberUser>().eq(MemberUser::getIcCard, importBean.getIcCard()));
                    if (count > 0) {
                        throw new ServiceException(500, "卡号重复!");
                    }
                }
                SysOrg sysOrg = sysOrgMapper.selectOne(new LambdaQueryWrapper<SysOrg>().eq(SysOrg::getCode, importBean.getOrgCode()));
                if (sysOrg == null) {
                    addFailMessage(memberImportResultPojoVos, importBean, "组织编码找不到所属组织!", failureNum);
                    continue;
                }
                if (!ObjectUtil.equal(sysOrg.getType(), 1)) {
                    throw new ServiceException(500, "请选择员工组!");
                }
                this.saveBean(successNum, importBean, sysOrg);
            } catch (Exception e) {
                log.error("用户【{}】 发生错误 错误信息【{}】", importBean.getName(), ExceptionUtils.getMessage(e));
                addFailMessage(memberImportResultPojoVos, importBean, "发生异常错误!" + ExceptionUtils.getMessage(e), failureNum);
            }
        }
    }

    private void addFailMessage(List<MemberImportResultPojoVO> memberImportResultPojoVos, MemberUserImportVO importBean, String failMessage, AtomicInteger failureNum) {
        MemberImportResultPojoVO memberImportResultPojoVo = new MemberImportResultPojoVO();
        memberImportResultPojoVo.setName(importBean.getName()).setFailMessage(failMessage);
        memberImportResultPojoVos.add(memberImportResultPojoVo);
        failureNum.incrementAndGet();
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
    public void saveBean(AtomicInteger successNum, MemberUserImportVO importBean, SysOrg sysOrg) {
        MemberUser memberUser;
        memberUser = new MemberUser();
        BeanUtils.copyProperties(importBean, memberUser);
        memberUser.setOrgId(sysOrg.getId());
        setMemberReadCardStatus(memberUser);

        if (StringUtils.isNotEmpty(importBean.getPhoto())) {
            String url = File.separator.concat("userImage").concat(File.separator).concat(importBean.getPhoto());
            memberUser.setPhoto(url);
//            memberUser.setPhoto( "/userImage/pic"+importBean.getPhoto().split("pic")[1]);
        }

        if (StringUtils.isNotBlank(importBean.getPosCode())) {
            SysPos one = posService.getOne(new LambdaQueryWrapper<SysPos>().eq(SysPos::getCode, importBean.getPosCode()));
            memberUser.setPosId(one.getId());
            memberUser.setPosName(one.getName());
        }

        memberUserService.save(memberUser);
        successNum.incrementAndGet();

        List<OrgDevice> orgDevices = orgDeviceMapper.selectList(new LambdaQueryWrapper<OrgDevice>().eq(OrgDevice::getOrgId, sysOrg.getId()));
        for (OrgDevice orgDevice : orgDevices) {
            MemberDevice memberDevice = new MemberDevice();
            memberDevice.setMemberId(memberUser.getId()).setDeviceId(orgDevice.getDeviceId()).setOrgId(memberUser.getOrgId()).setStatus(MemberDeviceConstant.ADD);
            memberDeviceMapper.insert(memberDevice);
        }
    }

    @Override
    public List<MemberUser> findByIdCard(String name, String idCardBegin4, String idCardEnd4) {
        return memberUserMapper.findByIdCard(name, idCardBegin4, idCardEnd4);
    }

    @Override
    public List<MemberUser> findUserNotInStore(int plat) {
        return memberUserMapper.findUserNotInStore(plat);
    }

    /**
     * + 获取内部人员
     *
     * @author 胡鹏达
     * @date 2022-07-09 15:48:24
     */
    private MemberUser queryMemberUser(MemberUserParam memberUserParam) {
        MemberUser memberUser = memberUserService.getById(memberUserParam.getId());
        if (ObjectUtil.isNull(memberUser)) {
            throw new ServiceException(MemberUserExceptionEnum.NOT_EXIST);
        }
        return memberUser;
    }
}
